
use super::{
    column::Column, form_props::FormProps, import_props::ImportProps, list_props::ListProps,
};
#[cfg(feature = "ssr")]
use crate::base::mysql::get_columns;
#[cfg(feature = "ssr")]
use crate::base::{Error, Result};
use crate::prelude::report::AuthFilter;
use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct CommonPage {
    /** 页面的标题*/
    pub title: Option<String>,
    /** 后台表的名字*/
    pub table_name: Option<String>,
    /** 权限过滤*/
    #[serde(default)]
    pub auth_filter: Option<AuthFilter>,
    /** 编辑窗口属性 */
    #[serde(default)]
    pub form_props: Option<FormProps>,
    /** 浏览表格属性 */
    #[serde(default)]
    pub list_props: Option<ListProps>,
    /** 表格数据的字段配置 */
    pub field_props: Vec<Column>,
    /** 导入属性 */
    #[serde(default)]
    pub import_props: Option<ImportProps>,
    #[serde(default)]
    pub insert_sql: Option<String>,
    #[serde(default)]
    pub update_sql: Option<String>,
    #[serde(default)]
    pub select_sql: Option<String>,
}
#[cfg(feature = "ssr")]
impl CommonPage {
    pub(crate) async fn parse(&mut self) -> Result<()> {
        if self.field_props.is_empty() {
            return Err(Error::from("field_props不能为空"));
        }
        if let Some(table_name) = &self.table_name {
            let fps = get_columns(table_name).await.or_else(|err| {
                Err(Error::from(format!(
                    "获取表{}的字段信息失败{err}",
                    table_name
                )))
            })?;
            //验证list_props
            if let Some(lps) = self.list_props.as_mut() {
                lps.parse(&fps, table_name)
                    .or_else(|err| Err(Error::from(format!("验证list_props失败：{err}"))))?;
            }
            //验证field_props
            for col in self.field_props.iter_mut() {
                col.parse(table_name, &fps)
                    .await
                    .or_else(|err| Err(Error::from(format!("验证field_props失败：{err}"))))?;
            }
            //验证import_props
            if let Some(ips) = &self.import_props {
                ips.parse(table_name, &fps)
                    .or_else(|err| Err(Error::from(format!("验证import_props失败：{err}"))))?;
            }
            let (select_sql, insert_sql, update_sql) = self
                .create_sql()
                .or_else(|err| Err(Error::from(format!("创建SQL语句失败：{err}"))))?;
            self.select_sql = Some(select_sql);
            self.insert_sql = Some(insert_sql);
            self.update_sql = Some(update_sql);
        } else {
            if self.list_props.is_some() {
                return Err(Error::from("浏览表格属性list_props需要指定dao_name"));
            }
            if self.import_props.is_some() {
                return Err(Error::from("导入属性import_props需要指定dao_name"));
            }
        }
        if let Some(lps) = &self.list_props {
            if lps.is_table_edit {
                if !self
                    .field_props
                    .iter()
                    .any(|f| f.list_props.as_ref().map(|lp| lp.edit).unwrap_or(false))
                {
                    return Err(Error::from("is_table_edit为true，但form_props中没有找到可编辑的字段"));
                }
            }
        }
        Ok(())
    }
    pub fn get_leaf_columns(&self) -> Vec<&Column> {
        let mut leafs: Vec<&Column> = vec![];
        for col in self.field_props.iter() {
            add_col(col, &mut leafs);
        }
        leafs
    }
    pub fn get_show_columns(&self) -> Vec<&str> {
        let mut show_cols: Vec<&str> = vec![];
        for col in self.field_props.iter() {
            add_col2(col, &mut show_cols);
        }
        show_cols
    }
    fn create_sql(&self) -> Result<(String, String, String)> {
        let tname = self
            .table_name
            .as_ref()
            .ok_or(Error::from("table_name不能为空"))?;
        let leafs = self.get_leaf_columns();
        if leafs.is_empty() {
            return Err(Error::from("没有可用的字段"));
        }
        let mut select_sql = "select ".to_string();
        let mut insert_sql = format!("insert into {} (", tname);
        let mut insert_sql_vals = "values (".to_string();
        let mut update_sql = format!("update {} set ", tname);
        let mut pk_col: Option<&str> = None;
        for col in leafs.iter() {
            let col_name = col.name.as_deref().ok_or(Error::from("col_name不能为空"))?;
            select_sql.push_str(&format!("`{}`,", col_name));
            if col.is_pk && col.is_auto_incr {
                pk_col = col.name.as_deref();
                continue;
            }
            insert_sql.push_str(&format!("`{}`,", col_name));
            insert_sql_vals.push_str("?,");
            update_sql.push_str(&format!("`{}`=?,", col_name));
        }
        select_sql.pop();
        select_sql.push_str(" from ");
        select_sql.push_str(tname);
        insert_sql.pop();
        insert_sql.push_str(") ");
        insert_sql_vals.pop();
        insert_sql_vals.push_str(") ");
        insert_sql.push_str(&insert_sql_vals);
        update_sql.pop();
        update_sql.push_str(" where ");
        if let Some(pk) = pk_col {
            update_sql.push_str(&format!("`{}`=?", pk));
        } else {
            return Err(Error::from(format!("表{tname}没有主键")));
        }
        Ok((select_sql, insert_sql, update_sql))
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum Position {
    Modal,
    Inner,
    Left,
    Right,
}
impl Default for Position {
    fn default() -> Self {
        Position::Modal
    }
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum Layout {
    Horizontal,
    Vertical,
}
impl Default for Layout {
    fn default() -> Layout {
        Layout::Vertical
    }
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub enum InitValue {
    UserId,
    Dept1Id,
    Dept2Id,
    CurrentDate,
    CurrentTime,
    Str(String),
}

fn add_col<'a, 'b>(col: &'a Column, cols: &'b mut Vec<&'a Column>) {
    if col.children.len() == 0 {
        cols.push(col)
    } else {
        for cc in col.children.iter() {
            add_col(cc, cols)
        }
    }
}
fn add_col2<'a, 'b>(col: &'a Column, cols: &'b mut Vec<&'a str>) {
    if col.children.len() == 0 {
        if let Some(lps) = col.list_props.as_ref() {
            if lps.display {
                cols.push(col.name.as_deref().unwrap_or(""));
            }
        }
    } else {
        for cc in col.children.iter() {
            add_col2(cc, cols)
        }
    }
}


